#ifndef MESH_H
#define MESH_H
#include "Export.h"
#include "Color4.h"
#include "IDrawable.h"
#include "LoaderFactory.h"
#include "Material.h"
namespace glow
{
struct Mesh_data
{
  float * _vertices ;
  float * _texcoord ;
  float * _normals;
  unsigned int * _index ;
  unsigned int _nb_vertices;
  unsigned int _nb_index;
  unsigned int _nb_texcoord;
  unsigned int _nb_normals;
};

  class SHARED Mesh :public IDrawable
  {	
	
  public :
	
  Mesh(Mesh_data Md):{
      _posX=0.;
      _posY=0.;
      _posZ=0.;
      _angleX = 0.;
      _angleY = 0.;
      _angleZ = 0.;
      _c.r=1.0;
      _c.g=1.0;
      _c.b=1.0;
      _c.a=1.0;
      _filename="";
      _texname="";
    
      /* 
       *  mesh_data
       *  
       * _vertices=NULL ;
       * _texcoord=NULL ;
       * _index=NULL ;
       * _normals=NULL;
       * _nb_vertices=0;
       * _nb_index=0;
       * _nb_texcoord=0;
       * _nb_normals=0;
       * 
       */  
    
	
    }
	
   
	
  void genNormal()
  {
    /* on ititialise le tableau de normales */
    _nb_normals=_nb_vertices;
    _normals=new float[_nb_normals*3];
    for(int i=0;i<_nb_normals*3;i++)
      {
	_normals[i]=0;
      }
    /* fin init */
    //cout<<"_normal init"<<endl;
    float u[3],v[3],n[3];
    /* on parcours les triangles */
    for(int j=0; j<_nb_index;j+=1)
      {
	/* on créé une normale pour chaque triangle */
	
	/* on recupere u avec les pts 1&2 du triangle */
	u[0]=_vertices[3*_index[j*3+1]]-_vertices[3*_index[j*3]];
	u[1]=_vertices[3*_index[j*3+1]+1]-_vertices[3*_index[j*3]+1];
	u[2]=_vertices[3*_index[j*3+1]+2]-_vertices[3*_index[j*3]+2];
	//cout<<"u recup"<<endl;
	/* on récupêre v avec les pts 1&3 du triangle */
	v[0]=_vertices[3*_index[j*3+2]]-_vertices[3*_index[j*3]];
	v[1]=_vertices[3*_index[j*3+2]+1]-_vertices[3*_index[j*3]+1];
	v[2]=_vertices[3*_index[j*3+2]+2]-_vertices[3*_index[j*3]+2];
	//cout<<"v recup"<<endl;
	/* on fais le produit scalaire de u&v */
	n[0] = (u[1]*v[2])-(u[2]*v[1]);
	n[1] = (u[2]*v[0])-(u[0]*v[2]);
	n[2] = (u[0]*v[1])-(u[1]*v[0]);
    
	/* on a notre normale du triangle _index & _index+1 & _index+2 */

	/* on normanize */
	float normanizer=sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);
	
	n[0] = n[0]/normanizer;
	n[1] = n[1]/normanizer;
	n[2] = n[2]/normanizer;
	
	/* on additionne a cette normale les normales stockées pour chaque point du triangle */
	_normals[3 * _index[j*3]] += n[0];
	_normals[3 * _index[j*3+1]] += n[0];
	_normals[3 * _index[j*3+2]] += n[0];
	
	_normals[3 * _index[j*3] + 1] += n[1];
	_normals[3 * _index[j*3+1] + 1] += n[1];
	_normals[3 * _index[j*3+2] + 1] += n[1];
	
	_normals[3 * _index[j*3] + 2] += n[2];
	_normals[3 * _index[j*3+1] + 2] += n[2];
	_normals[3 * _index[j*3+2] + 2] += n[2];
	
	
	//cout << "normal : "<< j<<endl;
      }
  }
    /* observateurs */
    float getPosX() const {return _posX;}
    float getPosY() const {return _posY;}
    float getPosZ() const {return _posZ;}
    float getAngleX() const {return _angleX;}  
    float getAngleY() const {return _angleY;}
    float getAngleZ() const {return _angleZ;}
    float * getVertices() const {return _vertices;}
    unsigned int * getIndex() const {return _index;}
    float * getTexCoord() const {return _texcoord;}
    float * getNormals() const {return _normals;}
    unsigned int getNbVertices() const {return _nb_vertices;}
    unsigned int getNbIndex() const {return _nb_index;}
    unsigned int getNbTexCoord() const {return _nb_texcoord;}
    unsigned int getNbNormals() const {return _nb_normals;}
    string getFilename() const {return _filename;}
    string getTexname() const {return _texname;}
    void get_All_mat() const { _m.get_All_Mat();}

    /* accesseurs */
    void setPosX(float x)
    {
      _posX = x;
    }
	  
    void setPosY(float y)
    {
      _posY = y;
    }
	
    void setPosZ(float z)
    {
      _posZ = z;
    }
	
    void setAngleX(float ax)
    {
      _angleX = ax ;
    }
	
    void setAngleY(float ay)
    {
      _angleY = ay ;
    }
	
    void setAngleZ(float az)
    {
      _angleZ = az ;
    }
	
    void setFilename(string fn)
    {
      _filename = fn ;
    }
	
    void setTexname(string tn)
    {
      _texname = tn ;
    }
			
    void move(float x, float y, float z)
    {
      _posX = x; _posY = y; _posZ = z;
    }
	
    void rotate(float ax, float ay, float az)
    {
      _angleX = ax ; _angleY = ay ; _angleZ = az ;
    }
	
    void colorer(float cr, float cg, float cb, float ca)
    {
      _c={cr,cg,cb,ca};
    }
	
    void set_mat_Ambient(GLfloat a, GLfloat b, GLfloat c, GLfloat d)
    {
      _m.set_Material_Ambient(a, b, c, d);
    }

    void set_mat_Diffuse(GLfloat a, GLfloat b, GLfloat c, GLfloat d)
    {    
      _m.set_Material_Diffuse(a, b, c, d);
    }

    void set_mat_Specular(GLfloat a, GLfloat b, GLfloat c, GLfloat d)
    {
      _m.set_Material_Specular(a, b, c, d);
    }

    void set_shininess(int sh)
    {
      _m.set_Shininess(sh);
    }
        
    virtual void load()=0;

  private:

    float 
      _posX,
      _posY,
      _posZ,
      _angleX,
      _angleY,
      _angleZ,
      _minZ;
    
    Color4f _c ; 
    Material _m;
	    
    float * _vertices ;
    float * _texcoord ;
    float * _normals;
	  
    unsigned int * _index ;
    unsigned int _nb_vertices;
    unsigned int _nb_index;
    unsigned int _nb_texcoord;
    unsigned int _nb_normals;
	  
    string _filename;
    string _texname;
	};
}		
    

#endif
